<template>
  <!-- <a-spin :spinning="spinning"> -->
  <div v-if="showTable">
    <div class="table-body-top">
      <div class="table-body-top-search">
        <TableScreening :tableName="tableName" @onClose="$emit('onClose')" @onSearch="$emit('onSearch')">
          <slot name="search" />
        </TableScreening>
        <slot name="search-right" />
      </div>
      <div style="text-align: right">
        <slot name="action-btn" />
        <slot name="action">
          <div v-if="!action" :style="$slots['action-btn'] ? 'margin-top:16px' : ''">
            <a-button
              v-if="$listeners['onReload']"
              class="action-btn"
              type="link"
              @click="
                () => {
                  $emit('onReload');
                  $message.success('刷新成功');
                }
              "
            >
              刷新 <a-icon type="reload" />
            </a-button>
            <a-divider v-if="selectHead" type="vertical" />
            <a-popover v-model="headVisible" title trigger="click" placement="bottomRight" overlayClassName="table-body-popover">
              <div slot="content" class="table-body-popover-content" :style="{ height: hasAddition ? '430px' : '330px' }">
                <div>
                  <div>已选择表头</div>
                  <div class="overview-tag-wrapper">
                    <Draggable v-model="tempSelectedHead" filter=".forbid" animation="30" :move="onMove">
                      <template v-for="(item, index) in tempSelectedHead">
                        <a-tag
                          v-if="!(isJF && item.dataIndex === 'postType')"
                          :key="`${item.title || item.customTitle}_${index}`"
                          :closable="item.isEdit"
                          :class="item.isEdit ? 'overview-select-tag' : 'overview-select-tag-name forbid'"
                          @close="deleteSelectedHead($event, index)"
                        >
                          {{ item.title || item.customTitle }}
                        </a-tag>
                      </template>
                    </Draggable>
                  </div>
                </div>
                <div>
                  <div>可选择表头</div>
                  <div class="overview-tag-noselect">
                    <div>
                      <template v-for="(item, index) in tempNoSelectedHead">
                        <a-tag
                          v-if="!(isJF && item.dataIndex === 'postType')"
                          :key="`${item.title || item.customTitle}_${index}`"
                          class="overview-no-select-tag"
                          @click="addSelectedHead(index, 'system')"
                        >
                          {{ item.title || item.customTitle }}
                        </a-tag>
                      </template>
                    </div>
                  </div>
                </div>
                <div v-if="hasAddition">
                  <div>自定义字段</div>
                  <div class="overview-tag-noselect">
                    <div>
                      <template v-for="(item, index) in customNoSelectedHead">
                        <a-tag
                          v-if="!(isJF && item.dataIndex === 'postType')"
                          :key="`${item.title || item.customTitle}_${index}`"
                          class="overview-no-select-tag"
                          @click="addSelectedHead(index, 'addition')"
                        >
                          {{ item.title || item.customTitle }}
                        </a-tag>
                      </template>
                    </div>
                  </div>
                </div>
                <a-row type="flex" justify="end" class="table-body-popover-btn">
                  <a-button style="margin-right: 12px" @click="handleHeadCancel">取消</a-button>
                  <a-button type="primary" @click="handleHeadSumbit" :loading="handleHeadSumbitLoading">保存</a-button>
                </a-row>
              </div>

              <a-button v-if="selectHead" class="action-btn" type="link"> 选择表头 <a-icon type="menu" /> </a-button>
            </a-popover>
            <slot v-if="!selectHead" name="selectHead" />
            <a-divider v-if="$listeners['onOrdered']" type="vertical" />
            <a-button v-if="$listeners['onOrdered']" class="action-btn" type="link" @click="$emit('onOrdered')">
              排序 <a-icon type="ordered-list" />
            </a-button>
            <template v-if="$slots['export']">
              <slot name="export" />
            </template>
            <template v-else>
              <a-divider v-if="$listeners['onExport'] || $listeners['onExportAll']" type="vertical" />
              <a-dropdown v-if="$listeners['onExport'] || $listeners['onExportAll']">
                <a-menu slot="overlay">
                  <a-menu-item v-if="$listeners['onExport'] && selection" key="1" @click="selectionBtnLock = true">批量导出</a-menu-item>
                  <a-menu-item v-if="$listeners['onExportAll']" key="2" :disabled="!source.length" @click="$emit('onExportAll')"
                    >全部导出</a-menu-item
                  >
                </a-menu>
                <a-button class="action-btn" type="link"> 导出 <a-icon type="caret-down" /> </a-button>
              </a-dropdown>
            </template>
          </div>
        </slot>
      </div>
    </div>
    <slot
      :className="'xq-draggable-table'"
      :columns="columnsArr"
      :components="components"
      :headerRowID="headerRowID"
      :scrollWidth="scrollWidth"
    />
    <div
      v-if="selection"
      class="table-body-footer"
      :class="
        ($listeners['onExport'] || selectionSlot) && (selectedRowKeys.length > 0 || selectionBtnLock)
          ? 'table-body-footer-enter'
          : 'table-body-footer-leave'
      "
      :style="{ width: `calc(100vw - ${this.tableBodyFooterWidth}px)`, left: `${this.tableBodyFooterWidth}px` }"
    >
      <div style="z-index: 9">
        选中 {{ selectedRowKeys.length }} 个
        <a-button type="link" :disabled="!selectedRowKeys.length" @click="$emit('update:selectedRowKeys', [])"> 清除 </a-button>
      </div>
      <a-button @click="TBFclose" class="mr12" v-if="!selectionSlot">取消</a-button>
      <a-button type="primary" :disabled="!selectedRowKeys.length" @click="$emit('onExport')" v-if="!selectionSlot"> 导出 </a-button>
      <slot name="selection-btn" />
    </div>
  </div>
  <!-- </a-spin> -->
</template>

<script>
import DraggableTableCell from "@/components/DraggableTableCell";
import Sortable from "sortablejs";
import Draggable from "vuedraggable";
import { getUpdateHead } from "./api";
import { tableNameJson, tableAdmin } from "./tableName";

export default {
  props: {
    subjectId: {
      type: String,
      default: ""
    },
    subjectType: {
      type: String,
      default: ""
    },
    needUpdateHead: {
      type: Boolean,
      default: false
    },
    hasAddition: {
      type: Boolean,
      default: false
    },
    tableHeadParams: {
      type: Object,
      default: () => ({})
    },
    tableHeadUrl: {
      type: String,
      default: "/admin/api/v1/headerFields/getHead"
    },
    isJF: {
      type: Boolean,
      default: false
    },
    /**
     * @type {string} 表格名称
     */
    tableName: {
      type: String,
      default: ""
    },
    /**
     * @type {string} 表格id
     */
    headerRowID: {
      type: String,
      default: ""
    },
    /**
     * @type {array} 默认表头数组
     */
    columns: {
      type: Array,
      default: () => []
    },
    /**
     * @type {array} 已选择的表头数组
     */
    selectedHead: {
      type: Array,
      default: () => []
    },
    /**
     * @type {boolean} 表格是否多选
     */
    selection: {
      type: Boolean,
      default: false
    },
    /**
     * @type {boolean} 未有导出方法时，表格是否弹出底部
     */
    selectionSlot: {
      type: Boolean,
      default: false
    },
    /**
     * @type {array} 选中数据
     */
    selectedRowKeys: {
      type: Array,
      default: () => []
    },
    /**
     * @type {array} 数据数组 获数据长度
     */
    source: {
      type: Array,
      default: () => []
    },
    /**
     * @type {boolean} 是否显示默认按钮
     */
    action: {
      type: Boolean,
      default: false
    },
    /**
     * @type {boolean} 是否显示选择表头
     */
    selectHead: {
      type: Boolean,
      default: false
    },
    /**
     * @type {boolean} 是否可以拖拽
     */
    drag: {
      type: Boolean,
      default: false
    }
  },
  components: {
    Draggable
  },
  data() {
    /**
     * @param {object} components 表格拖拽绑定 默认参数
     * @param {numbner} tableBodyFooterWidth 底部去除的宽度
     * @param {boolean} showTable 控制表格渲染
     * @param {boolean} headVisible 控制选择表头弹窗
     * @param {object} columnsJson 表头数据
     * @param {array} columnsArr 表头数据
     * @param {array} tempSelectedHead 已选的表头数据
     * @param {array} tempSelectedHeads 已选的表头数据 缓存
     * @param {array} tempNoSelectedHead 未选的表头数据
     * @param {array} tempNoSelectedHeads 未选的表头数据 缓存
     * @param {object} actionJson 操作栏缓存
     * @param {numbner} scrollWidth 表格长度
     */
    this.components = {};
    return {
      primary: localStorage.getItem("primary"),
      tableBodyFooterWidth: 0,
      spinning: true,
      showTable: false,
      headVisible: false,
      columnsJson: {},
      columnsArr: [],
      tempSelectedHead: [],
      tempSelectedHeads: [],
      tempNoSelectedHead: [],
      tempNoSelectedHeads: [],
      customNoSelectedHead: [],
      customNoSelectedHeads: [],
      additionAll: [],
      actionJson: null,
      scrollWidth: 1200,
      selectionBtnLock: false,
      handleHeadSumbitLoading: false,
      hadLoadedHead: false
    };
  },
  mounted() {
    this.getStyleWidth(this.$store.state.app.sidebar.opened);
    this.init();
  },
  watch: {
    "$store.state.app.sidebar.opened"(v) {
      this.getStyleWidth(v);
    },
    columns() {
      this.init();
    },
    selectedRowKeys(v) {
      if (v.length > 0) this.selectionBtnLock = true;
    }
  },
  methods: {
    init() {
      if (this.columns.length <= 0) {
        this.showTable = true;
        return false;
      }
      if (this.selectHead) {
        this.columns.forEach((e) => {
          if (!e.title) e.title = e.customTitle;
          this.columnsJson[e.title] = JSON.parse(JSON.stringify(e));
        });
        const title = this.columns[this.columns.length - 1].title;
        if (this.columns.length > 0) {
          if (title === "操作") {
            this.actionJson = this.columns[this.columns.length - 1];
          } else {
            this.columns.some((e) => {
              if (e.title === "操作") {
                this.actionJson = e;
                return false;
              }
            });
          }
        }
        this.onGetHead();
      } else {
        this.columnsArr = JSON.parse(JSON.stringify(this.columns));
        this.getColumns();
        this.initSortable();
      }
    },
    /**
     * @function 表格拖拽修改宽度绑定
     */
    getColumns() {
      let widthTemp = 0;
      this.columnsArr.forEach((e) => {
        if (e.dataIndex !== "action") {
          widthTemp += this.columnsJson[e.title]?.width || 150;
        }
      });
      this.components = {
        header: {
          cell: DraggableTableCell(this.columnsArr, true, widthTemp)
        }
      };
    },
    /**
     * @function 绑定拖拽修改位置方法
     */
    initSortable() {
      this.showTable = false;
      this.$nextTick(() => {
        this.showTable = true;
        this.$nextTick(() => {
          // if (!this.drag) return false;
          if (this.headerRowID) {
            new Sortable(document.getElementById(this.headerRowID), {
              onEnd: this.onDragEnd,
              handle: ".table-draggable-content"
            });
          }
        });
      });
    },
    /**
     * @function 表格拖拽修改位置
     * @param {array} columnsTemp 表头数组
     * @param {array} columnsTempNew 新表头数组
     * @param {object} columnsMap 表头数据筛选
     * @param {number} newIndex 新的位置下标
     * @param {number} oldIndex 旧的位置下标
     * @param {object} initArr 位置下标数组
     */
    onDragEnd(evt) {
      const newIndex = this.selection ? evt.newIndex - 1 : evt.newIndex;
      const oldIndex = this.selection ? evt.oldIndex - 1 : evt.oldIndex;
      const columnsTemp = [...this.columnsArr];
      const columnsMap = {};
      const initArr = [];
      for (let i = 0; i < columnsTemp.length; i++) {
        columnsMap[i] = columnsTemp[i];
        initArr.push(i);
      }
      initArr.splice(oldIndex, 1);
      initArr.splice(newIndex, 0, oldIndex);
      const columnsTempNew = initArr.map((idx) => columnsMap[idx]);
      const columnsTempNew2 = initArr.map((idx) => columnsMap[idx]);
      if (columnsTempNew2[columnsTempNew2.length - 1].title === "操作") {
        columnsTempNew2.pop();
      } else {
        columnsTempNew2.some((e, i) => {
          if (e === "操作") {
            columnsTempNew2.splice(i, 1);
            return false;
          }
        });
      }
      this.columnsArr = this.isJF ? columnsTempNew.filter((item) => item.dataIndex !== "postType") : columnsTempNew;
      this.tempSelectedHead = JSON.parse(JSON.stringify(columnsTempNew2));
      this.components = {
        header: {
          cell: DraggableTableCell(this.columnsArr)
        }
      };
      this.initSortable();
    },
    /**
     * @function 获取表头数据
     */
    getHeadArr() {
      const cArrTemp = JSON.parse(JSON.stringify(this.tempSelectedHead));
      if (this.actionJson) {
        cArrTemp.push(this.actionJson);
      }
      this.columnsArr = this.isJF ? cArrTemp.filter((item) => item.dataIndex !== "postType") : cArrTemp;
      this.$emit("update:selectedHead", this.tempSelectedHead);
      let widthTemp = 0;
      this.columnsArr.forEach((e) => {
        e.width = parseInt(e.width) || 150;
        widthTemp += e.width;
      });
      widthTemp += 60;
      const boxWidth = document.querySelector(".main-content").offsetWidth - 48;
      widthTemp = widthTemp > boxWidth ? widthTemp : boxWidth;
      this.scrollWidth = widthTemp;
    },
    async onGetHead() {
      try {
        const { data } = await this.$request({
          url: this.tableHeadUrl,
          method: "get",
          params: {
            subjectId: this.subjectId ? this.subjectId : tableAdmin.includes(this.tableName) ? null : this.$store.state.hr.companyId,
            "orders[0].property": "sort",
            "orders[0].desc": false,
            moduleCode: this.tableName,
            ...this.tableHeadParams
          }
        });
        this.filterArr(data);
        this.getHeadArr();
        this.getColumns();
        this.initSortable();
        this.$emit("headLoaded");

        if (this.needUpdateHead && !this.hadLoadedHead && data === null) {
          await this.onGetUpdateHead(true);
          this.hadLoadedHead = true;
          this.onGetHead();
        }
      } catch (err) {
        console.log("error log --> ", err);
      }
    },
    filterArr(data) {
      let tempSelectedHead = [];
      let tempNoSelectedHead = [];
      let customNoSelectedHead = [];
      if (data) {
        if (data.canSee && data.canSee.length > 0) {
          tempSelectedHead = data.canSee.map((e) => {
            const jsonParams = {
              title: e.fieldName,
              dataIndex: e.fieldEnName,
              isEdit: e.isEdit,
              id: e.id
            };
            const json = { ...this.columnsJson[e.fieldName], ...jsonParams };
            if (!json["width"]) {
              json["width"] = 150;
            }
            if (!json["scopedSlots"]) {
              json["scopedSlots"] = {
                customRender: e.fieldEnName
              };
            }
            return json;
          });
        }
        if (data.ignore && data.ignore.length > 0) {
          tempNoSelectedHead = data.ignore.map((e) => {
            const jsonParams = {
              title: e.fieldName,
              dataIndex: e.fieldEnName,
              isEdit: e.isEdit,
              id: e.id
            };
            const json = { ...this.columnsJson[e.fieldName], ...jsonParams };
            if (!json["width"]) {
              json["width"] = 150;
            }
            if (!json["scopedSlots"]) {
              json["scopedSlots"] = {
                customRender: e.fieldEnName
              };
            }
            return json;
          });
        }
        if (this.hasAddition && data.addition && data.addition.length > 0) {
          this.additionAll = data.additionAll.map((item) => item.fieldName);
          customNoSelectedHead = data.addition.map((e) => {
            const jsonParams = {
              title: e.fieldName,
              dataIndex: e.fieldEnName,
              isEdit: e.isEdit,
              id: e.id
            };
            const json = { ...this.columnsJson[e.fieldName], ...jsonParams };
            if (!json["width"]) {
              json["width"] = 150;
            }
            if (!json["scopedSlots"]) {
              json["scopedSlots"] = {
                customRender: e.fieldEnName
              };
            }
            return json;
          });
        }
        const dataArr = [...(data.canSee || []), ...(data.ignore || []), ...(this.hasAddition ? data.addition : [])].map(
          (e) => e.fieldName
        );
        const columnsArr = this.columns.map((e) => e.title);
        if (columnsArr[columnsArr.length - 1] === "操作") {
          columnsArr.pop();
        } else {
          columnsArr.some((e, i) => {
            if (e === "操作") {
              columnsArr.splice(i, 1);
              return false;
            }
          });
        }
        const d = columnsArr.filter((v) => !dataArr.includes(v));
        d.forEach((e) => {
          this.columnsJson[e].isEdit = this.columnsJson[e].isEdit || true;
          tempSelectedHead.push(this.columnsJson[e]);
        });
      } else {
        this.columns.forEach((e) => {
          if (e.title === "操作") return false;
          if (e?.isEdit === undefined) {
            e.isEdit = true;
          }
          if (e?.colDefault) {
            tempSelectedHead.push(e);
          } else {
            tempNoSelectedHead.push(e);
          }
        });
      }

      this.tempSelectedHead = JSON.parse(JSON.stringify(tempSelectedHead));
      this.tempSelectedHeads = JSON.parse(JSON.stringify(tempSelectedHead));
      this.tempNoSelectedHead = JSON.parse(JSON.stringify(tempNoSelectedHead));
      this.tempNoSelectedHeads = JSON.parse(JSON.stringify(tempNoSelectedHead));
      this.customNoSelectedHead = JSON.parse(JSON.stringify(customNoSelectedHead));
      this.customNoSelectedHeads = JSON.parse(JSON.stringify(customNoSelectedHead));
    },
    handleHeadSumbit() {
      this.onGetUpdateHead();
    },
    async onGetUpdateHead(hideMsg = false) {
      this.handleHeadSumbitLoading = true;
      try {
        const canSee = this.tempSelectedHead
          .filter((e) => e.id !== "fixed")
          .map((e) => {
            return {
              fieldName: e.title,
              fieldEnName: e.dataIndex,
              isEdit: e.isEdit
            };
          });
        const ignore = this.tempNoSelectedHead
          .filter((e) => e.id !== "fixed")
          .map((e) => {
            return {
              fieldName: e.title,
              fieldEnName: e.dataIndex,
              isEdit: e.isEdit
            };
          });
        const addition = this.customNoSelectedHead
          .filter((e) => e.id !== "fixed")
          .map((e) => {
            return {
              fieldName: e.title,
              fieldEnName: e.dataIndex,
              isEdit: e.isEdit
            };
          });
        await getUpdateHead({
          id: "all",
          subjectId: this.subjectId ? this.subjectId : tableAdmin.includes(this.tableName) ? null : this.$store.state.hr.companyId,
          subjectType: this.subjectType ? this.subjectType : tableAdmin.includes(this.tableName) ? "site" : "company",
          moduleCode: this.tableName,
          moduleType: tableNameJson[this.tableName],
          canSee,
          ignore,
          addition
        });
        this.getHeadArr();
        this.getColumns();
        this.initSortable();
        if (!hideMsg) {
          this.$message.success("保存成功");
        }
        this.handleHeadSumbitLoading = false;
        this.headVisible = false;
      } catch (err) {
        this.$message.error("保存失败");
        this.handleHeadSumbitLoading = false;
        console.log("error log --> ", err);
      }
    },
    handleHeadCancel() {
      this.headVisible = false;
      this.tempSelectedHead = JSON.parse(JSON.stringify(this.tempSelectedHeads));
      this.tempNoSelectedHead = JSON.parse(JSON.stringify(this.tempNoSelectedHeads));
      this.customNoSelectedHead = JSON.parse(JSON.stringify(this.customNoSelectedHeads));
      this.getHeadArr();
    },
    onMove(e) {
      if (!e.relatedContext.element.isEdit) return false;
      return true;
    },
    addSelectedHead(index, type) {
      const tempList = JSON.parse(JSON.stringify(type === "system" ? this.tempNoSelectedHead : this.customNoSelectedHead));
      const temp = tempList[index];
      tempList.splice(index, 1);
      if (type === "system") {
        this.tempNoSelectedHead = tempList;
      } else {
        this.customNoSelectedHead = tempList;
      }
      this.tempSelectedHead.push(temp);
    },
    deleteSelectedHead(e, index) {
      e.preventDefault();
      const temp = JSON.parse(JSON.stringify(this.tempSelectedHead[index]));
      this.tempSelectedHead.splice(index, 1);
      if (this.additionAll.includes(temp.title)) {
        this.customNoSelectedHead.push(temp);
      } else {
        this.tempNoSelectedHead.push(temp);
      }
    },
    getStyleWidth(v) {
      if (tableAdmin.includes(this.tableName)) {
        this.tableBodyFooterWidth = 188;
      } else {
        this.tableBodyFooterWidth = v ? 210 : 64;
      }
    },
    TBFclose() {
      this.$emit("update:selectedRowKeys", []);
      this.selectionBtnLock = false;
    }
  }
};
</script>

<style lang="scss" scoped>
.table-body-top {
  margin-bottom: 16px;
  display: flex;
  justify-content: space-between;
  .table-body-top-search {
    display: flex;
  }
  .action-btn {
    color: #767885;
    padding: 0;
    font-size: 12px;
    &:hover {
      color: var(--primary);
    }
  }
}
.table-body-popover {
  .table-body-popover-content {
    width: 600px;
    height: 330px;
  }
  .overview-tag-wrapper {
    height: 100px;
    display: flex;
    overflow-y: auto;
    flex-direction: column;
    ::v-deep .ant-tag {
      .anticon-close {
        color: var(--primary);
      }
    }
  }
  .overview-tag-noselect {
    height: 130px;
    display: flex;
    overflow-y: auto;
    flex-direction: column;
  }
  .overview-no-select-tag {
    background-color: #fff;
    cursor: pointer;
    margin: 5px;
  }
  .overview-select-tag-name {
    cursor: pointer;
    margin: 5px;
    color: #666666;
  }
  .overview-select-tag {
    background-color: #fff !important;
    color: var(--primary) !important;
    border: 1px solid var(--primary);
    cursor: pointer;
    margin: 5px;
  }
  .table-body-popover-btn {
    position: absolute;
    bottom: 20px;
    right: 20px;
  }
}

.table-body-footer {
  transition: all 0.4s linear;
  z-index: 999;
  height: 56px;
  line-height: 56px;
  padding: 0 24px;
  background: #ffffff;
  box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.15);
  text-align: center;
  position: fixed;
  bottom: -56px;
  div {
    position: absolute;
    left: 24px;
  }
}
.table-body-footer-enter {
  bottom: 0;
}
.table-body-footer-leave {
  bottom: -56px;
}
</style>
